/*
 * 文件名：ConfigManager.java
 * 版权：Copyright 2006-2010 Huawei Tech. Co. Ltd. All Rights Reserved. 
 * 描述： ConfigManager.java
 * 修改人：qipengfei
 * 修改时间：2010-7-2
 * 修改内容：新增
 */
package com.fengxing.ams.pub.manager;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.fengxing.ams.pub.AMSException;
import com.fengxing.ams.pub.constants.ReltCode;
import com.fengxing.ams.pub.manager.dao.ICollegeConfigDAO;
import com.fengxing.ams.pub.manager.dao.IConfigDAO;
import com.fengxing.ams.pub.manager.dao.IStatusDescDAO;
import com.fengxing.ams.pub.manager.dao.IUploadRuleDAO;
import com.fengxing.ams.pub.manager.intf.IConfigManager;
import com.fengxing.ams.pub.util.LogUtil;
import com.fengxing.ams.pub.vo.CollegeConfigVO;
import com.fengxing.ams.pub.vo.ConfigVO;
import com.fengxing.ams.pub.vo.StatusDescVO;
import com.fengxing.ams.pub.vo.UploadRuleVO;

/**
 * 配置管理类，线程安全
 * <p>
 * 配置管理类，线程安全
 * <p>
 * 
 * <pre>
 * </pre>
 * 
 * @author qipengfei
 * @version RCS CAB V100R00 2010-7-2
 * @since RCS CAB V100R002C01L00201
 */
@Component
public final class ConfigManager implements IConfigManager {
	/**
	 * Logger for this class
	 */
	private static final Log logger = LogFactory.getLog(ConfigManager.class);

	/**
	 * 配置系统VO，存放系统参数key<->value
	 */
	private Map<String, String> dbConfigs = new HashMap<String, String> ();

	/**
	 * 加载系统参数Service
	 */
	@Autowired
	private IConfigDAO configDAO;
	@Autowired
	private ICollegeConfigDAO collegeDAO;

	/**
	 * 是否被初始化
	 */
	private boolean isInitinted = false;

	/**
	 * 同步锁
	 */
	private final Lock lock = new ReentrantLock();

	private long expiredTime = Long.MAX_VALUE;

	/**
	 * 
	 * {@inheritDoc}
	 */
	public void initMethod() {
		if (logger.isInfoEnabled()) {
			LogUtil.info(logger, "ConfigManager|load|param|start|");
		}

		if (!isInitinted) {
			this.init();
		}
		if (logger.isInfoEnabled()) {
			LogUtil.info(logger, "ConfigManager|load|param|end|");
		}

	}

	/**
	 * {@inheritDoc}
	 */
	public String getProperty(String paramName, String defaultValue) {
		String paramValue = null;
		this.lock.lock();

		try {
			if (!isInitinted || (System.currentTimeMillis() > this.expiredTime)) {
				this.init();
			}
			String cfgVO = dbConfigs.get(paramName);

			if (cfgVO == null) {
				return defaultValue;
			}
			paramValue = cfgVO;

		} finally {
			this.lock.unlock();
		}
		if (logger.isDebugEnabled()) {
			LogUtil.debug(logger, "ConfigManager|get|property|paramName="
					+ paramName + "|paramValue=" + paramValue);
		}

		return paramValue;
	}

	/**
	 * {@inheritDoc}
	 */
	public void init() {

		this.lock.lock();

		try {
//			this.dbConfigs = this.configService.loadConfig();
			List<ConfigVO> configs = configDAO.findAll();
			for (ConfigVO configVO : configs) {
				if (configVO.getParam_key().equalsIgnoreCase("cache_timeout")) {
					this.expiredTime = System.currentTimeMillis() + Long.valueOf(configVO.getParam_value()) * 1000L;
				}
				dbConfigs.put(configVO.getParam_key(), configVO.getParam_value());
			}

			if (logger.isInfoEnabled()) {
				LogUtil.info(logger, "ConfigManager|" + this.dbConfigs);
			}

			this.isInitinted = true;

		} finally {
			this.lock.unlock();
		}

	}
	
	public void add(String paramKey, String value) {
		if(dbConfigs.containsKey(paramKey)) {
			throw new AMSException(ReltCode.SYSPARAM_ADD_FAILED);
		}
		dbConfigs.put(paramKey, value);
	}
	
	public void delete(String paramKey) {
		if(dbConfigs.containsKey(paramKey)) {
			dbConfigs.remove(paramKey);
		}
	}
	
	public void update(String paramKey, String value) {
		if(!dbConfigs.containsKey(paramKey)) {
			throw new AMSException(ReltCode.SYSPARAM_ALERT_FAILED);
		}
		dbConfigs.put(paramKey, value);
	}

	@Override
	public boolean isScoreRelease() {
		String scoreReleaseTimeS = this.getProperty("score_release_date", "2016-06-23 00:00:00");
		Date scoreReleaseTime = null;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			scoreReleaseTime = sdf.parse(scoreReleaseTimeS);
		} catch (ParseException e) {
			Calendar c = Calendar.getInstance();
			c.set(Calendar.YEAR, 2016);
			c.set(Calendar.MONTH, 6);
			c.set(Calendar.DAY_OF_MONTH, 23);
			c.set(Calendar.HOUR_OF_DAY, 0);
			c.set(Calendar.MINUTE, 0);
			c.set(Calendar.SECOND, 0);
			scoreReleaseTime = c.getTime();
		}
		boolean isRelease = false;
		if (new Date().after(scoreReleaseTime)) {
			isRelease = true;
		}
		return isRelease;
	}
	
	@Override
	public Date getScoreRelease() {
		String scoreReleaseTimeS = this.getProperty("score_release_date", "2016-06-23 00:00:00");
		Date scoreReleaseTime = null;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			scoreReleaseTime = sdf.parse(scoreReleaseTimeS);
		} catch (ParseException e) {
			Calendar c = Calendar.getInstance();
			c.set(Calendar.YEAR, 2016);
			c.set(Calendar.MONTH, 6);
			c.set(Calendar.DAY_OF_MONTH, 23);
			c.set(Calendar.HOUR_OF_DAY, 0);
			c.set(Calendar.MINUTE, 0);
			c.set(Calendar.SECOND, 0);
			scoreReleaseTime = c.getTime();
		}
		return scoreReleaseTime;
	}

	@Override
	public Map<Integer, Integer> getWeightConfig() {
		Map<Integer, Integer> weightConfig = new HashMap<Integer, Integer> ();
		String yearWeight = this.getProperty("year_weight", "");
		String[] splits = yearWeight.split(",");
		for (String split : splits) {
			String[] pairEntry = split.split(":");
			Integer year = Integer.valueOf(pairEntry[0]);
			Integer weight = Integer.valueOf(pairEntry[1]);
			weightConfig.put(year, weight);
		}
		return weightConfig;
	}

	@Override
	public Date getExpiredDate() {
		String expiredConfig = this.getProperty("expired_date", "");
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
		try {
			return sdf.parse(expiredConfig);
		} catch (Exception e) {
			Calendar c = Calendar.getInstance();
			c.set(Calendar.YEAR, 2016);
			c.set(Calendar.MONTH, 9);
			c.set(Calendar.DAY_OF_MONTH, 1);
			return c.getTime();
		}
	}

	private static final Map<String, Integer> COLLEGE_MAP = new HashMap<String, Integer> ();
	
	@Override
	public Integer getCollegeId(String collegeName) {
		if (COLLEGE_MAP.isEmpty()) {
			Iterator<CollegeConfigVO> iter = this.collegeDAO.findAll().iterator();
			while (iter.hasNext()) {
				CollegeConfigVO vo = iter.next();
				COLLEGE_MAP.put(vo.getCollegeName(), vo.getId());
			}
		}
		return COLLEGE_MAP.get(collegeName);
	}

	private static final Map<Integer, String> STATUS_MAP = new HashMap<Integer, String> ();
	
	@Autowired
	IStatusDescDAO statusDescDAO;
	
	@Override
	public String getStatusDesc(Integer status) {
		if (STATUS_MAP.isEmpty()) {
			Iterator<StatusDescVO> iter = statusDescDAO.findAll().iterator();
			while (iter.hasNext()) {
				StatusDescVO vo = iter.next();
				STATUS_MAP.put(vo.getStatus(), vo.getDesc());
			}
		}
		return STATUS_MAP.get(status);
	}

	private static final Map<String, UploadRuleVO> RULE_MAP = new HashMap<String, UploadRuleVO> ();
	@Autowired
	IUploadRuleDAO uploadRuleDAO;
	@Override
	public UploadRuleVO getTranlatorRule(Integer j, String type) {
		if (RULE_MAP.isEmpty()) {
			Iterator<UploadRuleVO> iter = uploadRuleDAO.findAll().iterator();
			while (iter.hasNext()) {
				UploadRuleVO rule = iter.next();
				RULE_MAP.put(rule.getType() + rule.getCellNum(), rule);
			}
		}
		return RULE_MAP.get(type + j);
	}
	
	private static final Set<String> STUDENTID_SET = new HashSet<String> ();
	
	private static final Lock idsetLock = new ReentrantLock();

	@Override
	public boolean isExist(String content) {
		idsetLock.lock();
		try {
			return STUDENTID_SET.contains(content);
		} finally {
			idsetLock.unlock();
		}
		
	}

	@Override
	public void addAllStudentId(List<String> studentIds) {
		idsetLock.lock();
		try {
			STUDENTID_SET.addAll(studentIds);
		} finally {
			idsetLock.unlock();
		}
		
	}

	@Override
	public void addStudentId(String content) {
		idsetLock.lock();
		try {
			STUDENTID_SET.add(content);
		} finally {
			idsetLock.unlock();
		}
		
	}

	@Override
	public void deleteStudentIds(List<String> ids) {
		idsetLock.lock();
		try {
			STUDENTID_SET.removeAll(ids);
		} finally {
			idsetLock.unlock();
		}
		
	}

	@Override
	public void syncIds(List<String> studentIds) {
		idsetLock.lock();
		try {
			STUDENTID_SET.clear();
			STUDENTID_SET.addAll(studentIds);
		} finally {
			idsetLock.unlock();
		}
	}

}
